package com.sunday.common.netty.e8_Handlerorder.server.inbound;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.nio.AbstractNioByteChannel;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class InBoundHandler1 extends ChannelInboundHandlerAdapter {


    /**
     * channelRead 触发规则
     * {@link io.netty.channel.AbstractChannelHandlerContext#invokeChannelRead(AbstractChannelHandlerContext, Object)}
     *
     *     static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
     *         final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
     *         EventExecutor executor = next.executor();
     *         if (executor.inEventLoop()) {
     *             next.invokeChannelRead(m);  // 按照调用链递归调用
     *         } else {
     *             executor.execute(new Runnable() {
     *                 @Override
     *                 public void run() {
     *                     next.invokeChannelRead(m);
     *                 }
     *             });
     *         }
     *     }
     *
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info("[In][1][Into] InBoundHandler.channelRead");

        String data = ((ByteBuf) msg).toString(CharsetUtil.UTF_8);
        log.info("[In][1][receive] InBoundHandler.channelRead receive: " + data);
        // If do not call fireChannelRead, the next ChannelHandler will not exec.
        ctx.fireChannelRead(msg);
        log.info("[In][1][Exit] InBoundHandler channelRead");
    }

    /**
     * channelReadComplete 触发规则
     * {@link AbstractNioByteChannel.NioByteUnsafe#read()}
     *
     *                 allocHandle.readComplete();
     *                 pipeline.fireChannelReadComplete(); // 触发下一个ChannelHandler的channelReadComplete 仅触发一次
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        log.info("[In][1][readComplete] InBoundHandler readComplete.");
        ctx.pipeline().remove(this);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info("[In][1][exceptionCaught] InBoundHandler exceptionCaught.");
    }
}
